/// @Classname : HcSteps
/// @Author :
/// @Time : 2023-09-11 9:55
/// @Description : //todo

import 'dart:math';

import 'package:flutter/material.dart';
import 'package:hc_ui/widget/divider/hc_divider.dart';
import 'package:hc_ui/widget/icon_text/hc_icon_text.dart';
import 'package:hc_ui/widget/space/hc_space.dart';

class HcStepsItem {
  int index = 0;

  //标题
  String title;

  //附加文案
  String? desc;

  //图标
  Widget? icon;

  //状态
  HcStepsState? state;

  //颜色
  Color? color;
  Widget? verticalContent;

  HcStepsItem(
      {required this.title,
      this.desc,
      this.icon,
      this.state,
      this.color,
      this.verticalContent});
}

// 状态
enum HcStepsState { complete, error, progress, wait }

typedef HcStepsCallback = Function(int index);

class HcSteps extends StatefulWidget {
  //方向
  final Axis direction;

  //内容组件
  final List<HcStepsItem> list;

  //当前位置
  final int index;

  //间隔符号
  final Widget? dividerWidget;

  //文字是否上方展示
  final bool textTopShow;

//  完成的图标
  final Widget completeIcon;

  //错误的图标
  final Widget errorIcon;

  //等待的图标
  final Widget? waitIcon;

  //等待的图标
  final Widget? progressIcon;

  //当前状态
  final HcStepsState currentState;

  //完成后的颜色
  final Color completeColor;

  //未完成的颜色
  final Color waitColor;

  //错误的颜色
  final Color errorColor;

  //当前进行中的颜色
  final Color? progressColor;

  //提示文案的文字样式
  final TextStyle descStyle;

  //标题的文字样式
  final TextStyle titleStyle;

  //点击的回调
  final HcStepsCallback? callback;

  //内边距
  final EdgeInsets padding;

  //Icon大小
  final double iconSize;

  //是否允许滚动
  final bool enableScroll;

  const HcSteps(
      {Key? key,
      this.direction = Axis.horizontal,
      required this.list,
      required this.index,
      this.dividerWidget,
      this.textTopShow = false,
      this.completeIcon = const Icon(Icons.check_circle_sharp),
      this.errorIcon = const Icon(Icons.error_rounded),
      this.waitIcon,
      this.currentState = HcStepsState.progress,
      this.completeColor = Colors.blue,
      this.waitColor = Colors.grey,
      this.errorColor = Colors.redAccent,
      this.descStyle = const TextStyle(color: Colors.grey, fontSize: 10),
      this.titleStyle = const TextStyle(color: Colors.black, fontSize: 14),
      this.progressColor,
      this.progressIcon,
      this.callback,
      this.padding = const EdgeInsets.symmetric(horizontal: 0, vertical: 10),
      this.iconSize = 22,
      this.enableScroll = false})
      : super(key: key);

  const HcSteps.dot(
      {Key? key,
      this.direction = Axis.horizontal,
      required this.list,
      this.index = 0,
      this.dividerWidget,
      this.textTopShow = false,
      this.currentState = HcStepsState.progress,
      this.completeColor = Colors.blue,
      this.waitColor = Colors.grey,
      this.errorColor = Colors.redAccent,
      this.descStyle = const TextStyle(color: Colors.grey, fontSize: 10),
      this.titleStyle = const TextStyle(color: Colors.black, fontSize: 14),
      this.progressColor,
      this.padding = const EdgeInsets.symmetric(horizontal: 8, vertical: 10),
      this.iconSize = 22,
      this.callback,
      this.enableScroll = false})
      : waitIcon = const Icon(
          Icons.radio_button_off_rounded,
          size: 22,
        ),
        progressIcon = const Icon(
          Icons.radio_button_checked_sharp,
          size: 22,
        ),
        errorIcon = const Icon(
          Icons.circle_rounded,
          size: 22,
        ),
        completeIcon = const Icon(
          Icons.circle_rounded,
          size: 22,
        ),
        super(key: key);

  @override
  State<HcSteps> createState() => _HcStepsState();
}

class _HcStepsState extends State<HcSteps> {
  double widgetWidth = 0;
  double spacing = 8.0;
  late ScrollController _controller;

  @override
  void initState() {
    // TODO: implement initState
    super.initState();
    _controller = ScrollController();
  }

  @override
  void didUpdateWidget(covariant HcSteps oldWidget) {
    // TODO: implement didUpdateWidget
    super.didUpdateWidget(oldWidget);
    if (_controller.hasClients && _controller.position.maxScrollExtent > 0) {
      _controller.jumpTo(_controller.position.maxScrollExtent *
          (widget.index / (widget.list.length - 1)));
    }
  }

  @override
  void dispose() {
    // TODO: implement dispose
    super.dispose();
    _controller.dispose();
  }

  @override
  Widget build(BuildContext context) {
    List<HcStepsItem> finalList = List.empty(growable: true);
    double _maxWidth = 80;
    bool isVertical = widget.direction == Axis.vertical;
    bool isTextTopShow = !isVertical && widget.textTopShow;
    finalList = widget.list.asMap().entries.map((element) {
      int currentIndex = element.key;
      HcStepsItem item = element.value;
      item.index = currentIndex;
      //如果是当前选项
      if (currentIndex == widget.index) {
        item.state = widget.currentState;
      } else {
        item.state ??= (currentIndex < widget.index)
            ? HcStepsState.complete
            : HcStepsState.wait;
      }
      item = _buildItem(item);
      return item;
    }).toList();

    return LayoutBuilder(builder: (context, container) {
      widgetWidth =
          container.maxWidth - widget.padding.left - widget.padding.right;
      double itemWidth = widgetWidth / finalList.length;
      bool enableScroll = widget.enableScroll ||
          (itemWidth - spacing * 2 - widget.iconSize < 0);
      itemWidth = max(itemWidth, enableScroll ? _maxWidth : 0);
      List<Widget> child = finalList
          .map((item) => Stack(
                alignment: isTextTopShow
                    ? AlignmentDirectional.bottomStart
                    : AlignmentDirectional.topStart,
                children: [
                  GestureDetector(
                    onTap: () {
                      if (widget.callback != null) {
                        widget.callback!.call(item.index);
                      }
                    },
                    child: SizedBox(
                      width: isVertical ? null : itemWidth,
                      child: HcIconText(
                        spacing: spacing,
                        direction: isVertical ? Axis.horizontal : Axis.vertical,
                        crossAxisAlignment: isVertical
                            ? CrossAxisAlignment.start
                            : CrossAxisAlignment.center,
                        reverse: isTextTopShow,
                        icon: IconTheme(
                          data: Theme.of(context).iconTheme.copyWith(
                              color: item.color, size: widget.iconSize),
                          child: item.icon ??
                              Container(
                                width: widget.iconSize,
                                height: widget.iconSize,
                                decoration: BoxDecoration(
                                    color: item.index == widget.index
                                        ? item.color
                                        : null,
                                    border: Border.all(
                                        color: item.color!, width: 1),
                                    borderRadius: BorderRadius.circular(
                                        widget.iconSize / 2)),
                                child: Center(
                                  child: Text(
                                    "${item.index + 1}",
                                    style: TextStyle(
                                        color: item.index == widget.index
                                            ? Colors.white
                                            : Colors.black),
                                  ),
                                ),
                              ),
                        ),
                        label: isVertical
                            ? Flexible(
                                flex: 1,
                                child: buildContent(
                                    isVertical, item, isTextTopShow),
                              )
                            : ConstrainedBox(
                                constraints:
                                    BoxConstraints(maxWidth: _maxWidth),
                                child: buildContent(
                                    isVertical, item, isTextTopShow),
                              ),
                      ),
                    ),
                  ),
                  if (item.index < finalList.length - 1)
                    if (isVertical)
                      buildVerticalLine(item)
                    else
                      buildHorizontalLine(
                          isTextTopShow, itemWidth, item, context),
                ],
              ))
          .toList();
      if (widget.direction == Axis.horizontal) {
        return SingleChildScrollView(
          controller: _controller,
          scrollDirection: widget.direction,
          child: Padding(
            padding: widget.padding,
            child: Row(
              mainAxisAlignment: MainAxisAlignment.center,
              crossAxisAlignment: CrossAxisAlignment.start,
              children: child,
            ),
          ),
        );
      }
      return Padding(
        padding: widget.padding,
        child: ListView(
          physics: const NeverScrollableScrollPhysics(),
          shrinkWrap: true,
          children: child,
        ),
      );
    });
  }

  Column buildContent(bool isVertical, HcStepsItem item, bool isTextTopShow) {
    return Column(
      crossAxisAlignment:
          isVertical ? CrossAxisAlignment.start : CrossAxisAlignment.center,
      children: [
        Container(
          margin: EdgeInsets.only(bottom: spacing / 2),
          child: Text(
            item.title,
            textAlign: isVertical ? TextAlign.start : TextAlign.center,
            maxLines: isTextTopShow ? 1 : null,
            overflow: isTextTopShow ? TextOverflow.ellipsis : null,
            style: widget.titleStyle.copyWith(
                color:
                    item.index == widget.index ? item.color : widget.waitColor,
                height: 1,
                fontWeight: item.index == widget.index
                    ? FontWeight.bold
                    : FontWeight.normal),
          ),
        ),
        if (!isTextTopShow)
          Text(
            item.desc ?? '',
            style: widget.descStyle,
            textAlign: isVertical ? TextAlign.start : TextAlign.center,
          ),
        if (isVertical && item.verticalContent != null)
          Container(
            margin: EdgeInsets.only(top: spacing),
            child: item.verticalContent!,
          ),
        if (isVertical)
          HcSpace(
            height: spacing * 2,
          )
      ],
    );
  }

  Positioned buildVerticalLine(item) {
    return Positioned(
      top: widget.iconSize + spacing / 2,
      bottom: spacing / 2,
      left: widget.dividerWidget != null ? 0 : widget.iconSize / 2,
      child: buildDelimiter(true, 0, item, context),
    );
  }

  Transform buildHorizontalLine(
      isTextTopShow, double itemWidth, HcStepsItem item, BuildContext context) {
    return Transform.translate(
      offset: Offset(itemWidth / 2 + widget.iconSize / 2 + spacing,
          (isTextTopShow ? -1 : 1) * widget.iconSize / 2),
      child: buildDelimiter(false, itemWidth, item, context),
    );
  }

  //构建间隔符
  Widget buildDelimiter(
      isVertical, double itemWidth, HcStepsItem item, BuildContext context) {
    return SizedBox(
      width: isVertical ? 1 : max(itemWidth - spacing * 2 - widget.iconSize, 0),
      height: isVertical || widget.dividerWidget != null ? null : 1,
      child: widget.dividerWidget ??
          HcDivider(
            decoration: isVertical ? Axis.vertical : Axis.horizontal,
            style: item.index < widget.index
                ? HcDividerStyle.solid
                : HcDividerStyle.dashed,
            spacing: isVertical
                ? 1
                : max(itemWidth - spacing * 2 - widget.iconSize, 0),
            thickness: 1,
            color: item.index < widget.index
                ? widget.completeColor
                : widget.waitColor,
          ),
    );
  }

  HcStepsItem _buildItem(HcStepsItem item) {
    if (item.index > widget.index) {
      item.color = widget.waitColor;
      item.icon = widget.waitIcon;
      return item;
    }
    switch (item.state) {
      case HcStepsState.complete:
        item.color ??= widget.completeColor;
        item.icon ??= widget.completeIcon;
        break;
      case HcStepsState.error:
        item.color ??= widget.errorColor;
        item.icon ??= widget.errorIcon;
        break;
      case HcStepsState.wait:
        item.color ??= widget.waitColor;
        item.icon ??= widget.waitIcon;
        break;
      case HcStepsState.progress:
        item.color = (widget.progressColor ?? widget.completeColor);
        item.icon = (widget.progressIcon ?? widget.waitIcon);
        break;
      default:
        break;
    }
    return item;
  }
}
